<template>
  <input type="text" v-model="obj.name" />
  <input type="text" v-model="obj.age" />
  <button @click="show">show</button>
  <br />
  <ul>
    <li v-for="item in list.arr">{{ item }}</li>
  </ul>
  <button @click="getList">get</button>
  <h2>{{ obj3 }}</h2>
  <button @click="obj2.name += '='">update obj2</button>
  <button @click="update">update obj1</button>
  <h2>{{ obj4 }}</h2>
  <button @click="obj4.name += '='">浅update</button>
  <button @click="obj4.friend.name += '='">深update</button>
  <h2>obj5 {{ obj5 }}</h2>
  <button @click="updateObj5">shallowReadonly</button>
</template>
<script setup lang="ts">
import { reactive, readonly, shallowReactive, shallowReadonly } from 'vue'

// reactive 参数仅能为引用类型(数组或对象)，返回值为一个深度响应的 Proxy 代理对象
// 不能对其返回值的对象进行直接重写操作，否则会重写 Proxy 为普通对象，失去响应
// 故一般使用 reactive 包裹非直接操作的对象，再将对象或数组形式的数据以属性形式存储
// const reactiveObj: Proxy = reactive(obj: object)

// shallowReactive 参数为引用类型,返回值为浅层响应的 Proxy 代理对象
// 即对浅层数据操作时才会更新页面,对深层数据操作时,仅能体现在数据上,不会更新页面
// 当在同一步操作包含 reactive 和 shallowReactive 的数据进行修改时
// reactive 数据会触发更新页面,将 shallowReactive 数据同时更新到页面上
// 故 shallowReactive 和 reactive 二者一般不在同一步连用
// const shallowReactiveObj: Proxy = reactive(obj: object)

// readonly 参数为引用类型，返回值为深度只读的 Readonly 对象
// 即操作 Readonly 对象时 warn 警告，且不会发生变化
// 但是对参数对象可以进行操作，而对参数对象操作也会体现在对 Readonly 对象上
// Readonly 为非响应式对象,不会根据数据变化更新页面
// const readonlyObj: Readonly = readonly(obj: object)

// shallowReadonly 参数为引用类型,返回值为浅层只读的 Readonly 对象
// 即操作浅层的 Readonly 对象数据时,会 warn 警告,且不会发送变化
// 但对深层次的 Readonly 对象数据操作时,不会阻止其行为
// const readonlyObj: Readonly = shallowReadonly(obj: object)

// Obj 接口
interface Obj {
  name: string
  age: number
}
// obj Proxy 对象
const obj = reactive<Obj>({
  name: 'Tom',
  age: 18,
})
// show 方法
const show = () => {
  console.log(obj)
}
// list Proxy 数组
let list = reactive<{ arr: string[] }>({
  arr: [],
})
// getList 获取数组值方法
const getList = () => {
  setTimeout(() => {
    // 不能直接对 reactive 返回的对象进行重写操作，因为返回 Proxy 对象，重写后为新对象，会丧失响应功能
    list.arr = ['a', 'b', 'c']
    console.log(list)
  }, 2000)
}
const obj1: Obj = {
  name: 'Mike',
  age: 20,
}
// obj2 对象为 readonly 只读对象
// 对于操作 readonly 返回的只读对象时会 warn 警告
const obj2: Obj = readonly(obj1)
// 如果对原始原始数据进行操作，跳过 readonly 对象，则可以实现修改
// update 方法，操作 obj1 对象实现对只读对象 obj2 的修改
const update = () => {
  obj.name += '='
  console.log(obj3)
}
// obj3 为只读的 Proxy 代理对象，可以通过对 obj 的修改来实现 obj3 的修改
const obj3: Obj = readonly(obj)
// obj4 为浅层的 Proxy 代理对象,即当其浅层数据变化时才会更新页面
const obj4: any = shallowReactive({
  name: 'Marry',
  friend: {
    name: 'Tom',
  },
})
const obj5: any = shallowReadonly(obj4)
const updateObj5 = () => {
  obj5.name += '='
  console.log(obj5)
}
</script>
<style scoped></style>
